package com.zwl.swagger;

import com.alibaba.fastjson.JSONObject;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaType;
import com.zwl.swagger.comment.Comment;
import com.zwl.swagger.comment.MethodComment;
import com.zwl.swagger.util.SwaggerFileUtil;
import com.zwl.swagger.util.SwaggerReflectUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangweilin
 * @Description:
 * @date 2021年08月20日 20:59
 */
public class CommentCollector {
    private static final Log log = LogFactory.getLog(CommentCollector.class);

    private static final Comment COMMENT = new Comment();
    private static final String configFilePath = "/META-INF/swagger-doc-desc/";

    static void collector(String srcPath, String classPath) {
        collector(new File(srcPath), classPath);
    }

    static void collector(File file, String classPath) {
//        System.out.println("文件编码file.encoding: "+System.getProperty("file.encoding"));

        JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
		javaProjectBuilder.setEncoding("UTF-8");
        javaProjectBuilder.addSourceTree(file);
        Collection<JavaClass> classes = javaProjectBuilder.getClasses();

        for (JavaClass javaClass : classes) {
            String fullClassName = javaClass.toString().replace("class ", "");
            String simpleName = javaClass.getSimpleName();

            //类注释
            String classCommentText = javaClass.getComment();
            if (StringUtils.isEmpty(classCommentText)) {
                List<DocletTag> tags = javaClass.getTags();
                if (null != tags && !tags.isEmpty()) {
                    for (DocletTag tag : tags) {
                        String name = tag.getName();
                        String value = tag.getValue();
                        if (!StringUtils.isEmpty(name) && name.startsWith("Description")) {
                            if (!StringUtils.isEmpty(value)) {
                                value = value.replaceAll("\\s.*", "");
                            }
                            classCommentText = value;
                            break;
                        }

                    }
                }
            }
            if (StringUtils.isEmpty(classCommentText)) {
                classCommentText = simpleName;
            }

            classCommentText = convertToCn(classCommentText);
            COMMENT.getClassCommentMap().put(fullClassName, classCommentText);

            // 获得方法列表
            List<JavaMethod> methods = javaClass.getMethods();
            for (JavaMethod method : methods) {
                String methodName = method.getName();

                MethodComment methodComment = new MethodComment();
                String methodCommentText = method.getComment();
                methodCommentText = convertToCn(methodCommentText);
//                System.out.println("methodCommentText = " + methodCommentText);
                methodComment.setComment(methodCommentText);

                Map<String, String> paramCommentMap = new LinkedHashMap<>();
                List<DocletTag> tagList = method.getTags();
                for (DocletTag docletTag : tagList) {
                    String name = docletTag.getName();
                    String value = docletTag.getValue();
                    String key = value.replaceAll("\\s.*", "");
                    value = value.replace(key, "").trim();

                    if ("param".equals(name)) {
                        value = convertToCn(value);
                        paramCommentMap.put(key, value);
                    }
                }
                methodComment.setParamCommentMap(paramCommentMap);

                List<JavaType> parameterTypes = method.getParameterTypes();
                StringBuilder methodDesc = new StringBuilder("(");
                StringBuilder methodDesc2 = new StringBuilder("(");
                for (int i = 0; i < parameterTypes.size(); i++) {
                    JavaType javaType = parameterTypes.get(i);
                    Object name = SwaggerReflectUtil.getFieldValue(javaType, "name");
//					Object fullName = ReflectUtil.getFieldValue(javaType, "fullName");
					Object fullName = javaType.toString();
                    methodDesc.append(name);
					methodDesc2.append(fullName);
                    if (i != parameterTypes.size() - 1) {
                        methodDesc.append(", ");
						methodDesc2.append(", ");

                    }
                }
                methodDesc.append(")");
				methodDesc2.append(")");

                String classCommentKey = fullClassName + "#" + methodName + methodDesc;
                String classCommentKey2 = fullClassName + "#" + methodName + methodDesc2;
                COMMENT.getMethodCommentMap().put(classCommentKey, methodComment);
                COMMENT.getMethodCommentMap().put(classCommentKey2, methodComment);
            }

            List<JavaField> fields = javaClass.getFields();
            for (JavaField field : fields) {
                String name = field.getName();
                String comment = field.getComment();

                comment = convertToCn(comment);
//                System.out.println("comment = " + comment);
                String fieldsCommentKey = fullClassName + "#" + name;
                COMMENT.getFieldCommentMap().put(fieldsCommentKey, comment);
            }
        }
//        System.out.println("COMMENT = " + COMMENT);
        String json = JSONObject.toJSONString(COMMENT);
		log.info("get comment doc conent: " + json);
//        if (log.isDebugEnabled()) {
//            log.debug("get comment doc conent: " + json);
//        }

        String rootPath = classPath + configFilePath;
        SwaggerFileUtil.createDir(rootPath);
        File file1 = file;
        for (int i = 0; i < 3 && file1 != null; i++) {
            file1 = file1.getParentFile();
        }
        String projectName = file1.getName();
        String fileName = projectName + ".json";
        SwaggerFileUtil.writeFile(fileName, rootPath, json);
        log.info("comment doc content wrote successful!,file path:" + (rootPath + fileName));
    }

	/**
	 * todo 这里仍有少量的见鬼的乱码问题
	 * @param methodCommentText
	 * @return
	 */
    private static String convertToCn(String methodCommentText) {
        if (StringUtils.isNotEmpty(methodCommentText)) {
//			log.info("methodCommentText转乱码前 = " + methodCommentText);
//			try {
//                methodCommentText = new String(methodCommentText.getBytes("GBK"), "UTF-8");
//            } catch (Throwable e) {
//                e.printStackTrace();
//            }
//			log.info("methodCommentText转乱码后 = " + methodCommentText);
		}
        return methodCommentText;
    }
}
